package Build;

use strict;
use warnings;
use Cwd;

# Export the public subroutines to programs that use this module 
BEGIN {
  require Exporter;
  our @ISA = qw(Exporter);
  our @EXPORT = qw();

}

my $type; #build type: baseline or cron
my $conf; #build conf: Debug, Release or ReleaseRTLx
my $number; #build number
my $trunk_directory; #trunk path
my $build_tool_directory; #build_tool path
my $build_name; #build name
my $compiler_err_warn = "compiler_error_and_warn.txt"; #compiler errors and warnings file
my $linker_err_warn = "linker_error_and_warn.txt"; #linker errors and warnings file

###############################################################################
# Function: setBuildProper
# This subroutine sets the type, configuration and number properties. It also
# calls the checkBuildNumber to verify the build number. 
#
# Inputs: Type, configuration and build name.
# Returns: Nothing.
###############################################################################

sub setBuildProper {
	$type = $_[1];
	$conf = $_[2];
	$build_name = $_[3];
	#initializing the build tool directory path
	$build_tool_directory = getcwd();
	
}

###############################################################################
# Function: buildCode
# This subroutine goes to the code directory and builds the code using 
# the command "make" depending on the build configuration (Release, ReleaseRTLx or Debug).
#
# Inputs: Trunk directory path.
# Returns: Nothing.  
###############################################################################

sub buildCode{
	$trunk_directory = $_[1];
	my $conf = $_[2];
	#Get the current path (build tool directory)
	my $build_tool_directory = getcwd();
	my $code_directory = $trunk_directory . "/code";
	#Go to the code directory to make the build
	chdir($code_directory);
	#Build code based on its configuration (Debug, Release, ReleaseRTLx)
	# we are in the code directory, so there is only one makefile thatwe can
	# reference with the -f command in the command line below
	my $cmd = "make -f makefile BuildType=$conf all"; 
	print "Now building code with command $cmd\nPlease wait...\n";
	
	# we need to redirect STDOUT and STDERR to a file so we can post process
	# the file for warning and errors
	# that is what the '&' before the '>' does.
	system "$cmd &> the_build_output.txt";	
	#Go back to the build tool directory
	chdir($build_tool_directory);
}

###############################################################################
# Function: updateRelHist
#  This subroutine updates the release history if it's not the first build and
# neither the first baseline. Otherwise, it creates a new release history file.
# The release history file format is the most recent build at the top of the list 
#
# Inputs: First build flag, release history, build type and number
# Returns: Nothing.  
###############################################################################
sub updateRelHist{
#First build flag
my $first_build = $_[1];
#Relase history file name
my $release_history = $_[2];
my $type = $_[3];
my $number = $_[4];

#If it's not the first build it will copy the 
#old release history and add the new line
if($first_build eq "false"){
	#Old file
	my $file1 = "<" . $release_history;
	#Updated file
	my $file2 = ">" . $release_history . "_temp";
	open(FILE1, $file1) or die "Couldn't open rel_history.txt";	
	open(FILE2, $file2) or die "Couldn't create new rel_history.txt";
	#Add the new build tag in the first line
	if($type eq "baseline"){
		print FILE2 "base".$number . "\n";
	}
	elsif($type eq "cron"){
		print FILE2 "cron".$number . "\n";
	}
	#Copy the rest of the lines from old file
	while(<FILE1>){    
		print FILE2 $_;
	}
	close FILE2;
	close FILE1;
	#Delete old file
	unlink($release_history);
	#Rename updated file
	rename $release_history . "_temp", $release_history; 
	print "\n $release_history updated\n";
}
#If it's the first build it will create the rel_h
else {
	#Create the release history file and add the tag
	open(FILE, ">" . $release_history) or die "Couldn't create new rel_history.txt";
	if($type eq "baseline"){
		print FILE "base".$number . "\n";
		
	}
	elsif($type eq "cron"){
		print FILE "cron".$number . "\n";
	}
	close FILE;	
	print "\n $release_history created\n";
	#If it's the first build, the tool needs to add the file, because it was created
	system("svn add $release_history");
}

}

###############################################################################
# Function: analyzeCompLinkErr
#  This subroutine analyzes if there's compiler or linker errors and warnings.
# If the base_warn_suppress is enabled and there're compiler or linker warnings, 
#it will display a warning and continue with the build procedure. If it's not 
# enabled, the build tool will fail. If there're errors, the build tol will also 
#fail.
#
# Inputs: Base warnings flag, buildInfo and build configuration
# Returns: 0 for unsuccessful build.  1 for successful build.
###############################################################################
sub analyzeCompLinkEW {
	my $line;
	my $base_warn_suppress = $_[1];
	my $conf = $_[2];
	my $pathToSourceCode = $_[3];

	#Go to the build folder
	my $err_path = $trunk_directory . "/$build_name/" . $conf;
	
	#See if there're compiler warnings/errors
	open(COMP,$pathToSourceCode . "/the_build_output.txt") or die "Couldn't open the_build_output.txt file";
	while($line = <COMP>){
		#Warnings case: the tool will fail if the flag is not enabled and it is a baseline
		if ($line =~ m/Warning: /){
			if(($type eq "baseline") && ($base_warn_suppress eq "false")){
				print "\nThere're compiler or linker warnings and the base_warn_suppress is not enabled. Can't make the build.See the_build_output.txt for more information\n";
				close COMP;
				return 0;
			}
		}
		#Errors case: the tool will fail if there's an error. It doesn't matter if it is a cron or baseline
		if ($line =~ m/Error: /){
			print "\nThere're compiler or linker errors. Can't make the build. See the_build_output.txt for more information\n";
			close COMP;
			return 0;
		}
	}
	close COMP;
	
	return 1; # success
}

###############################################################################
# Function: updateBuildReportStatus
# This subroutine adds the successful status into the buildReport and moves it
#to the build folder.   
#
# Inputs: Build report path, build report name
# Returns:Nothing.
###############################################################################

sub updateBuildReportStatus{
	my $final_build_report_path = $_[1];
	my $buildReport = $_[2];
	my $pathToSourceCode = $_[3];
	my $status = $_[4];
	#Read the buildReport, add the status after the run time
	#and move the file to the build folder
	open(IN, "<$buildReport");
	open(OUT, ">$final_build_report_path");
	while(my $line = <IN>) {
		if ($line =~ /RUN TIME/){
			print OUT "BUILD STATUS: $status\n";
		}
		print OUT $line;
	}
	close IN;
	# now, append the output of the build to the build report file
	print OUT "\n\nOutput of build follows:\n\n";
	open(IN, "<$pathToSourceCode/the_build_output.txt");
	while(my $line = <IN>) 
	{
		print OUT $line;
	}
	close IN;
	close OUT;
	system("rm -rf $buildReport");
	system("rm -rf $pathToSourceCode/the_build_output.txt");
	
}

1;
